home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windows Game Programming for Dummies (2nd Edition)
/
WinGamProgFD.iso
/
mac
/
DirectX SDK
/
DXSDK
/
samples
/
Multimedia
/
Direct3D
/
DXTex
/
dxtexview.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2001-10-08
|
30KB
|
1,071 lines
// dxtexView.cpp : implementation of the CDxtexView class
//
#include "stdafx.h"
#include "dxtex.h"
#include "dxtexDoc.h"
#include "dxtexView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// Our custom vertex type
struct CUSTOMVERTEX
{
FLOAT x, y, z;
FLOAT rhw;
DWORD color;
FLOAT tu, tv; // The texture coordinates
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1)
IMPLEMENT_DYNCREATE(CDxtexView, CScrollView)
BEGIN_MESSAGE_MAP(CDxtexView, CScrollView)
//{{AFX_MSG_MAP(CDxtexView)
ON_WM_LBUTTONUP()
ON_COMMAND(ID_FILE_OPENSUBSURFACE, OnFileOpenSubsurface)
ON_COMMAND(ID_FILE_OPENALPHASUBSURFACE, OnFileOpenAlphaSubsurface)
ON_COMMAND(ID_FILE_OPENFACE, OnFileOpenFace)
ON_COMMAND(ID_FILE_OPENALPHAFACE, OnFileOpenAlphaFace)
ON_COMMAND(ID_VIEW_ORIGINAL, OnViewOriginal)
ON_COMMAND(ID_VIEW_COMPRESSED, OnViewCompressed)
ON_COMMAND(ID_VIEW_SMALLERMIPLEVEL, OnViewSmallerMipLevel)
ON_COMMAND(ID_VIEW_LARGERMIPLEVEL, OnViewLargerMipLevel)
ON_COMMAND(ID_VIEW_ALPHACHANNEL, OnViewAlphaChannel)
ON_COMMAND(ID_VIEW_ZOOMIN, OnViewZoomIn)
ON_COMMAND(ID_VIEW_ZOOMOUT, OnViewZoomOut)
ON_COMMAND(ID_VIEW_CHANGEBACKGROUNDCOLOR, OnViewChangeBackgroundColor)
ON_COMMAND(ID_VIEW_NEGX, OnViewNegX)
ON_COMMAND(ID_VIEW_POSX, OnViewPosX)
ON_COMMAND(ID_VIEW_NEGY, OnViewNegY)
ON_COMMAND(ID_VIEW_POSY, OnViewPosY)
ON_COMMAND(ID_VIEW_NEGZ, OnViewNegZ)
ON_COMMAND(ID_VIEW_POSZ, OnViewPosZ)
ON_COMMAND(ID_VIEW_HIGHERVOLUMESLICE, OnViewHigherVolumeSlice)
ON_COMMAND(ID_VIEW_LOWERVOLUMESLICE, OnViewLowerVolumeSlice)
ON_UPDATE_COMMAND_UI(ID_FILE_OPENSUBSURFACE, OnUpdateFileOpenSubsurface)
ON_UPDATE_COMMAND_UI(ID_FILE_OPENALPHASUBSURFACE, OnUpdateFileOpenAlphaSubsurface)
ON_UPDATE_COMMAND_UI(ID_FILE_OPENFACE, OnUpdateFileOpenFace)
ON_UPDATE_COMMAND_UI(ID_FILE_OPENALPHAFACE, OnUpdateFileOpenAlphaFace)
ON_UPDATE_COMMAND_UI(ID_VIEW_ORIGINAL, OnUpdateViewOriginal)
ON_UPDATE_COMMAND_UI(ID_VIEW_COMPRESSED, OnUpdateViewCompressed)
ON_UPDATE_COMMAND_UI(ID_VIEW_ALPHACHANNEL, OnUpdateViewAlphaChannel)
ON_UPDATE_COMMAND_UI(ID_VIEW_LARGERMIPLEVEL, OnUpdateViewLargerMipLevel)
ON_UPDATE_COMMAND_UI(ID_VIEW_SMALLERMIPLEVEL, OnUpdateViewSmallerMipLevel)
ON_UPDATE_COMMAND_UI(ID_VIEW_ZOOMIN, OnUpdateViewZoomIn)
ON_UPDATE_COMMAND_UI(ID_VIEW_ZOOMOUT, OnUpdateViewZoomOut)
ON_UPDATE_COMMAND_UI(ID_VIEW_NEGX, OnUpdateViewNegX)
ON_UPDATE_COMMAND_UI(ID_VIEW_POSX, OnUpdateViewPosX)
ON_UPDATE_COMMAND_UI(ID_VIEW_NEGY, OnUpdateViewNegY)
ON_UPDATE_COMMAND_UI(ID_VIEW_POSY, OnUpdateViewPosY)
ON_UPDATE_COMMAND_UI(ID_VIEW_NEGZ, OnUpdateViewNegZ)
ON_UPDATE_COMMAND_UI(ID_VIEW_POSZ, OnUpdateViewPosZ)
ON_UPDATE_COMMAND_UI(ID_VIEW_HIGHERVOLUMESLICE, OnUpdateViewHigherVolumeSlice)
ON_UPDATE_COMMAND_UI(ID_VIEW_LOWERVOLUMESLICE, OnUpdateViewLowerVolumeSlice)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CDxtexView::CDxtexView()
{
m_pVB = NULL;
m_ptexCur = NULL;
m_pSwapChain = NULL;
m_lwMipCur = 0;
m_CubeFaceCur = D3DCUBEMAP_FACE_FORCE_DWORD;
m_lwSliceCur = -1;
m_fZoom = 1.0f;
m_bViewOrig = TRUE;
m_bViewAlpha = FALSE;
}
CDxtexView::~CDxtexView()
{
ReleasePpo(&m_pVB);
ReleasePpo(&m_ptexCur);
ReleasePpo(&m_pSwapChain);
}
// Note: repaints don't require re-rendering, just recopy from back buffer to view's DC
void CDxtexView::OnDraw(CDC* pDC)
{
CDxtexDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
HRESULT hr;
CRect rcSrc;
CRect rcDest;
rcSrc = m_rcSrc;
rcDest = m_rcDest;
rcDest.OffsetRect(pDC->GetViewportOrg());
// REVIEW: only update dirty region?
if (m_pSwapChain != NULL)
hr = m_pSwapChain->Present(&rcSrc, &rcDest, GetSafeHwnd(), NULL);
}
#ifdef _DEBUG
void CDxtexView::AssertValid() const
{
CScrollView::AssertValid();
}
void CDxtexView::Dump(CDumpContext& dc) const
{
CScrollView::Dump(dc);
}
CDxtexDoc* CDxtexView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDxtexDoc)));
return (CDxtexDoc*)m_pDocument;
}
#endif //_DEBUG
void CDxtexView::OnLButtonUp(UINT nFlags, CPoint point)
{
// Button click means toggle compressed / uncompressed view
if (m_bViewOrig)
OnViewCompressed();
else
OnViewOriginal();
CScrollView::OnLButtonUp(nFlags, point);
}
void CDxtexView::OnInitialUpdate()
{
#ifdef _WIN64
SetClassLongPtr(GetSafeHwnd(), GCLP_HBRBACKGROUND, (LONG_PTR)CreateSolidBrush(RGB(100, 100, 120)));
#else
SetClassLong(GetSafeHwnd(), GCL_HBRBACKGROUND, (LONG)CreateSolidBrush(RGB(100, 100, 120)));
#endif
if (GetDocument()->IsCubeMap())
m_CubeFaceCur = D3DCUBEMAP_FACE_POSITIVE_X;
else
m_CubeFaceCur = D3DCUBEMAP_FACE_FORCE_DWORD;
if (GetDocument()->IsVolumeMap())
m_lwSliceCur = 0;
BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
UpdateDevice();
CreateVertexBuffer();
RenderScene();
SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height()));
ResizeParentToFit();
CScrollView::OnInitialUpdate();
m_bTitleModsChanged = TRUE; // force title bar update
}
VOID CDxtexView::GetImageInfo(CString& strInfo)
{
LPDIRECT3DBASETEXTURE8 ptex;
D3DSURFACE_DESC sd;
D3DVOLUME_DESC vd;
D3DFORMAT fmt;
DWORD dwWidth;
DWORD dwHeight;
DWORD dwDepth;
CString strFormat;
TCHAR sz[100];
DWORD dwBytes = 0;
UINT iLevel;
if (m_bViewOrig)
ptex = GetDocument()->PtexOrig();
else
ptex = GetDocument()->PtexNew();
if (GetDocument()->IsVolumeMap())
{
((LPDIRECT3DVOLUMETEXTURE8)ptex)->GetLevelDesc(0, &vd);
fmt = vd.Format;
dwWidth = vd.Width;
dwHeight = vd.Height;
dwDepth = vd.Depth;
}
else if (!GetDocument()->IsCubeMap())
{
((LPDIRECT3DTEXTURE8)ptex)->GetLevelDesc(0, &sd);
fmt = sd.Format;
dwWidth = sd.Width;
dwHeight = sd.Height;
dwDepth = 0;
}
else
{
((LPDIRECT3DCUBETEXTURE8)ptex)->GetLevelDesc(0, &sd);
fmt = sd.Format;
dwWidth = sd.Width;
dwHeight = sd.Height;
dwDepth = 0;
}
strFormat = FormatName(fmt);
// Count bytes in main surface chain
if (GetDocument()->IsVolumeMap())
{
for (iLevel = 0; iLevel < GetDocument()->NumMips(); iLevel++)
{
((LPDIRECT3DVOLUMETEXTURE8)ptex)->GetLevelDesc(iLevel, &vd);
dwBytes += vd.Size;
}
}
else if (!GetDocument()->IsCubeMap())
{
dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_FORCE_DWORD, ptex);
}
else
{
dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_POSITIVE_X, ptex);
dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_NEGATIVE_X, ptex);
dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_POSITIVE_Y, ptex);
dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_NEGATIVE_Y, ptex);
dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_POSITIVE_Z, ptex);
dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_NEGATIVE_Z, ptex);
}
if (dwDepth == 0)
wsprintf(sz, "%d x %d, %s, %d bytes", dwWidth, dwHeight, strFormat, dwBytes);
else
wsprintf(sz, "%d x %d x %d, %s, %d bytes", dwWidth, dwHeight, dwDepth, strFormat, dwBytes);
strInfo = sz;
}
DWORD CDxtexView::NumBytesInSurfaces(D3DCUBEMAP_FACES FaceType, LPDIRECT3DBASETEXTURE8 ptex)
{
DWORD dwBytes = 0;
LPDIRECT3DTEXTURE8 pmiptex = NULL;
LPDIRECT3DCUBETEXTURE8 pcubetex = NULL;
D3DSURFACE_DESC sd;
DWORD iLevel;
if (FaceType == D3DCUBEMAP_FACE_FORCE_DWORD)
pmiptex = (LPDIRECT3DTEXTURE8)ptex;
else
pcubetex = (LPDIRECT3DCUBETEXTURE8)ptex;
for (iLevel = 0; iLevel < GetDocument()->NumMips(); iLevel++)
{
if (pmiptex != NULL)
pmiptex->GetLevelDesc(iLevel, &sd);
else
pcubetex->GetLevelDesc(iLevel, &sd);
dwBytes += sd.Size;
}
return dwBytes;
}
HRESULT CDxtexView::UpdateDevice(VOID)
{
HRESULT hr;
LPDIRECT3D8 pd3d = PDxtexApp()->Pd3d();
LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev();
D3DDISPLAYMODE dispMode;
D3DPRESENT_PARAMETERS presentParams;
pd3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dispMode);
ReleasePpo(&m_pSwapChain);
ZeroMemory(&presentParams, sizeof(presentParams));
presentParams.Windowed = TRUE;
presentParams.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;
presentParams.BackBufferWidth = m_rcSrc.Width();
presentParams.BackBufferHeight = m_rcSrc.Height();
presentParams.BackBufferFormat = dispMode.Format;
if (FAILED(hr = pd3ddev->CreateAdditionalSwapChain(&presentParams, &m_pSwapChain)))
return hr;
COLORREF crBkgd;
crBkgd = PDxtexApp()->GetProfileInt("Settings", "Background Color", RGB(0, 255, 255));
m_dwClearColor = D3DCOLOR_RGBA(GetRValue(crBkgd), GetGValue(crBkgd), GetBValue(crBkgd), 255);
return S_OK;
}
HRESULT CDxtexView::CreateVertexBuffer(VOID)
{
LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev();
// Create the the vertex buffer
if( FAILED( pd3ddev->CreateVertexBuffer( 6 * sizeof(CUSTOMVERTEX),
0 /* Usage */, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &m_pVB ) ) )
{
return E_FAIL;
}
return S_OK;
}
HRESULT CDxtexView::RenderScene(VOID)
{
CWaitCursor waitCursor;
HRESULT hr;
LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev();
LPDIRECT3DSURFACE8 psurf;
if (m_pSwapChain == NULL)
return E_FAIL;
// Vertices for our quad
CUSTOMVERTEX vertexArray[] =
{
// x, y, z, rhw, color
{ 0.0f, 0.0f, 0.5f, 1.0f, 0xffffffff, 0.0, 0.0, },
{ (FLOAT)m_rcSrc.right, 0.0f, 0.5f, 1.0f, 0xffffffff, 1.0, 0.0, },
{ (FLOAT)m_rcSrc.right, (FLOAT)m_rcSrc.bottom, 0.5f, 1.0f, 0xffffffff, 1.0, 1.0, },
{ (FLOAT)m_rcSrc.right, (FLOAT)m_rcSrc.bottom, 0.5f, 1.0f, 0xffffffff, 1.0, 1.0, },
{ 0.0f, (FLOAT)m_rcSrc.bottom, 0.5f, 1.0f, 0xffffffff, 0.0, 1.0, },
{ 0.0f, 0.0f, 0.5f, 1.0f, 0xffffffff, 0.0, 0.0, },
};
// Copy the global vertex data into the vertex buffer
VOID* pVertices;
if( FAILED( m_pVB->Lock( 0, sizeof(vertexArray), (BYTE**)&pVertices, 0 ) ) )
return E_FAIL;
memcpy( pVertices, vertexArray, sizeof(vertexArray) );
m_pVB->Unlock();
hr = m_pSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &psurf);
hr = pd3ddev->SetRenderTarget(psurf, NULL);
ReleasePpo(&psurf);
hr = pd3ddev->Clear(0, NULL, D3DCLEAR_TARGET, m_dwClearColor, 0.0f, 0);
hr = pd3ddev->BeginScene();
// If the texture uses premultiplied alpha, the source blend should be D3DBLEND_ONE
// since RGB is already at the level we want. With nonpremultiplied alpha, the
// source blend should be D3DBLEND_SRCALPHA.
D3DSURFACE_DESC sd;
m_ptexCur->GetLevelDesc(0, &sd);
if (!m_bViewAlpha && (sd.Format == D3DFMT_DXT2 || sd.Format == D3DFMT_DXT4))
{
if (FAILED(hr = pd3ddev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE)))
return hr;
}
else
{
if (FAILED(hr = pd3ddev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA)))
return hr;
}
hr = pd3ddev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
hr = pd3ddev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pd3ddev->SetTexture(0, m_ptexCur);
pd3ddev->SetStreamSource( 0, m_pVB, sizeof(CUSTOMVERTEX) );
pd3ddev->SetVertexShader( D3DFVF_CUSTOMVERTEX );
pd3ddev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );
pd3ddev->SetTexture(0, NULL);
hr = pd3ddev->EndScene();
return S_OK;
}
void CDxtexView::OnViewOriginal()
{
if (GetDocument()->PtexOrig() == NULL)
return;
BuildViewSurface(TRUE, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
RenderScene();
m_bTitleModsChanged = TRUE; // force title bar update
InvalidateRect(&m_rcDest, FALSE); // force redraw of this view
}
void CDxtexView::OnViewCompressed()
{
if (GetDocument()->PtexNew() == NULL)
return;
BuildViewSurface(FALSE, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
RenderScene();
m_bTitleModsChanged = TRUE; // force title bar update
InvalidateRect(&m_rcDest, FALSE); // force redraw of this view
}
void CDxtexView::OnUpdateViewOriginal(CCmdUI* pCmdUI)
{
if (GetDocument()->PtexOrig() == NULL)
{
pCmdUI->Enable(FALSE);
pCmdUI->SetCheck(0);
}
else
{
pCmdUI->Enable(TRUE);
pCmdUI->SetCheck(m_bViewOrig);
}
}
void CDxtexView::OnUpdateViewCompressed(CCmdUI* pCmdUI)
{
if (GetDocument()->PtexNew() == NULL)
{
pCmdUI->Enable(FALSE);
pCmdUI->SetCheck(0);
}
else
{
pCmdUI->Enable(TRUE);
pCmdUI->SetCheck(!m_bViewOrig);
}
}
void CDxtexView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
m_bTitleModsChanged = TRUE; // force title bar update
if (lHint == 1)
{
BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
RenderScene();
}
else if (lHint == 2)
{
UpdateDevice();
RenderScene();
}
else if (lHint == 3)
{
RenderScene();
}
CScrollView::OnUpdate(pSender, lHint, pHint);
}
void CDxtexView::OnViewSmallerMipLevel()
{
m_lwMipCur++;
if (m_lwSliceCur > 0)
m_lwSliceCur /= 2;
BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
UpdateDevice();
RenderScene();
m_bTitleModsChanged = TRUE; // force title bar update
SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height()));
Invalidate(); // force redraw of this view
}
void CDxtexView::OnViewLargerMipLevel()
{
m_lwMipCur--;
if (m_lwSliceCur > 0)
m_lwSliceCur *= 2;
BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
UpdateDevice();
RenderScene();
m_bTitleModsChanged = TRUE; // force title bar update
SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height()));
Invalidate(); // force redraw of this view
}
void CDxtexView::OnViewAlphaChannel(VOID)
{
BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, !m_bViewAlpha);
RenderScene();
Invalidate(); // force redraw of this view
m_bTitleModsChanged = TRUE; // force title bar update
}
void CDxtexView::OnUpdateViewAlphaChannel(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_bViewAlpha);
}
void CDxtexView::OnUpdateViewLargerMipLevel(CCmdUI* pCmdUI)
{
if (m_lwMipCur > 0)
pCmdUI->Enable(TRUE);
else
pCmdUI->Enable(FALSE);
}
void CDxtexView::OnUpdateViewSmallerMipLevel(CCmdUI* pCmdUI)
{
if (m_lwMipCur < (LONG)GetDocument()->NumMips() - 1)
pCmdUI->Enable(TRUE);
else
pCmdUI->Enable(FALSE);
}
void CDxtexView::OnViewZoomIn()
{
if (m_fZoom < 8.0f)
m_fZoom *= 2.0f;
m_rcDest.right = (LONG)(m_rcSrc.right * m_fZoom);
m_rcDest.bottom = (LONG)(m_rcSrc.bottom * m_fZoom);
SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height()));
m_bTitleModsChanged = TRUE; // force title bar update
Invalidate(); // force redraw of this view
}
void CDxtexView::OnViewZoomOut()
{
if (m_fZoom > 0.125f)
m_fZoom /= 2.0f;
m_rcDest.right = (LONG)(m_rcSrc.right * m_fZoom);
m_rcDest.bottom = (LONG)(m_rcSrc.bottom * m_fZoom);
SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height()));
m_bTitleModsChanged = TRUE; // force title bar update
Invalidate(); // force redraw of this view
}
void CDxtexView::OnUpdateViewZoomIn(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_fZoom < 8.0f);
}
void CDxtexView::OnUpdateViewZoomOut(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_fZoom > 0.125f);
}
CString CDxtexView::GetStrTitleMods(VOID)
{
CString strTitleMods;
strTitleMods = "(";
// Append alpha, if in alpha mode
if (m_bViewAlpha)
strTitleMods += "Alpha, ";
// Show format
LPDIRECT3DBASETEXTURE8 ptex;
CString strFormat;
D3DFORMAT fmt;
if (m_bViewOrig)
ptex = GetDocument()->PtexOrig();
else
ptex = GetDocument()->PtexNew();
if (GetDocument()->IsVolumeMap())
{
D3DVOLUME_DESC vd;
((LPDIRECT3DVOLUMETEXTURE8)ptex)->GetLevelDesc(0, &vd);
fmt = vd.Format;
}
else if (!GetDocument()->IsCubeMap())
{
D3DSURFACE_DESC sd;
((LPDIRECT3DTEXTURE8)ptex)->GetLevelDesc(0, &sd);
fmt = sd.Format;
}
else
{
D3DSURFACE_DESC sd;
((LPDIRECT3DCUBETEXTURE8)ptex)->GetLevelDesc(0, &sd);
fmt = sd.Format;
}
strTitleMods += FormatName(fmt);
strTitleMods += TEXT(", ");
// Append cube map info, if a cube map
switch (m_CubeFaceCur)
{
case D3DCUBEMAP_FACE_NEGATIVE_X:
strTitleMods += "Negative X, ";
break;
case D3DCUBEMAP_FACE_POSITIVE_X:
strTitleMods += "Positive X, ";
break;
case D3DCUBEMAP_FACE_NEGATIVE_Y:
strTitleMods += "Negative Y, ";
break;
case D3DCUBEMAP_FACE_POSITIVE_Y:
strTitleMods += "Positive Y, ";
break;
case D3DCUBEMAP_FACE_NEGATIVE_Z:
strTitleMods += "Negative Z, ";
break;
case D3DCUBEMAP_FACE_POSITIVE_Z:
strTitleMods += "Positive Z, ";
break;
}
if (m_lwSliceCur >= 0)
{
CString strSlice;
strSlice.Format("Slice %d of %d, ", m_lwSliceCur + 1, GetDocument()->DwDepthAt(m_lwMipCur));
strTitleMods += strSlice;
}
// Append mip info, if multiple mip levels
DWORD dwNumMips = GetDocument()->NumMips();
if (dwNumMips > 1)
{
CString strMipInfo;
strMipInfo.Format("Mip %d of %d, ", m_lwMipCur + 1, dwNumMips);
strTitleMods += strMipInfo;
}
// Append view magnification
CString strView;
strView.Format("%d", (LONG)(100 * m_fZoom));
strTitleMods += strView + "%";
strTitleMods += ")";
return strTitleMods;
}
CString CDxtexView::FormatName(D3DFORMAT fmt)
{
CString str;
switch (fmt)
{
case D3DFMT_A8R8G8B8:
str = TEXT("A8R8G8B8");
break;
case D3DFMT_A1R5G5B5:
str = TEXT("A1R5G5B5");
break;
case D3DFMT_A4R4G4B4:
str = TEXT("A4R4G4B4");
break;
case D3DFMT_R8G8B8:
str = TEXT("R8G8B8");
break;
case D3DFMT_R5G6B5:
str = TEXT("R5G6B5");
break;
case D3DFMT_X8R8G8B8:
str = TEXT("X8R8G8B8");
break;
case D3DFMT_X1R5G5B5:
str = TEXT("X1R5G5B5");
break;
case D3DFMT_R3G3B2:
str = TEXT("R3G3B2");
break;
case D3DFMT_A8R3G3B2:
str = TEXT("A8R3G3B2");
break;
case D3DFMT_X4R4G4B4:
str = TEXT("X4R4G4B4");
break;
case D3DFMT_DXT1:
str = TEXT("DXT1");
break;
case D3DFMT_DXT2:
str = TEXT("DXT2");
break;
case D3DFMT_DXT3:
str = TEXT("DXT3");
break;
case D3DFMT_DXT4:
str = TEXT("DXT4");
break;
case D3DFMT_DXT5:
str = TEXT("DXT5");
break;
default:
str = TEXT("unknown fmt");
break;
}
return str;
}
void CDxtexView::OnViewChangeBackgroundColor()
{
CHOOSECOLOR cc;
COLORREF crArray[16];
ZeroMemory(&cc, sizeof(cc));
cc.lStructSize = sizeof(cc);
cc.hwndOwner = GetSafeHwnd();
cc.rgbResult = PDxtexApp()->GetProfileInt("Settings", "Background Color", RGB(0, 255, 255));
cc.lpCustColors = crArray;
cc.Flags = CC_RGBINIT | CC_ANYCOLOR | CC_FULLOPEN;
if (ChooseColor(&cc))
{
PDxtexApp()->WriteProfileInt("Settings", "Background Color", cc.rgbResult);
// Update all views of all documents of our one doc template
POSITION posTemp = PDxtexApp()->GetFirstDocTemplatePosition();
CDocTemplate* pDocTemplate = PDxtexApp()->GetNextDocTemplate(posTemp);
CDocument* pdoc;
POSITION pos = pDocTemplate->GetFirstDocPosition();
while (pos != NULL)
{
pdoc = pDocTemplate->GetNextDoc(pos);
pdoc->UpdateAllViews(NULL, 2);
}
}
}
void CDxtexView::OnFileOpenSubsurface()
{
GetDocument()->OpenSubsurface(m_CubeFaceCur, m_lwMipCur, m_lwSliceCur);
}
void CDxtexView::OnUpdateFileOpenSubsurface(CCmdUI* pCmdUI)
{
pCmdUI->Enable(TRUE);
}
void CDxtexView::OnFileOpenAlphaSubsurface()
{
GetDocument()->OpenAlphaSubsurface(m_CubeFaceCur, m_lwMipCur, m_lwSliceCur);
}
void CDxtexView::OnUpdateFileOpenAlphaSubsurface(CCmdUI* pCmdUI)
{
pCmdUI->Enable(TRUE);
}
HRESULT CDxtexView::BuildViewSurface(BOOL bOrig, D3DCUBEMAP_FACES FaceType, LONG lwSlice, LONG lwMip, BOOL bViewAlpha)
{
HRESULT hr;
LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev();
LPDIRECT3DBASETEXTURE8 ptex;
BOOL bIsCubeMap = GetDocument()->IsCubeMap();
BOOL bIsVolumeMap = GetDocument()->IsVolumeMap();
D3DSURFACE_DESC sd;
D3DVOLUME_DESC vd;
ReleasePpo(&m_ptexCur);
if (bIsVolumeMap && lwSlice == -1)
lwSlice = 0;
if (bIsCubeMap && FaceType == D3DCUBEMAP_FACE_FORCE_DWORD)
FaceType = D3DCUBEMAP_FACE_POSITIVE_X;
m_bViewOrig = bOrig;
m_bViewAlpha = bViewAlpha;
m_lwSliceCur = lwSlice;
m_lwMipCur = lwMip;
m_CubeFaceCur = FaceType;
if (bOrig)
ptex = GetDocument()->PtexOrig();
else
ptex = GetDocument()->PtexNew();
if (bIsVolumeMap)
{
((LPDIRECT3DVOLUMETEXTURE8)ptex)->GetLevelDesc(m_lwMipCur, &vd);
sd.Width = vd.Width;
sd.Height = vd.Height;
}
else if (!bIsCubeMap)
{
((LPDIRECT3DTEXTURE8)ptex)->GetLevelDesc(m_lwMipCur, &sd);
}
else
{
((LPDIRECT3DCUBETEXTURE8)ptex)->GetLevelDesc(m_lwMipCur, &sd);
}
hr = pd3ddev->CreateTexture(sd.Width, sd.Height, 1,
0 /* Usage */, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_ptexCur);
if (FAILED(hr))
return hr;
m_rcSrc.SetRect(0, 0, sd.Width, sd.Height);
m_rcDest.SetRect(0, 0, (INT)(sd.Width * m_fZoom), (INT)(sd.Height * m_fZoom));
LPDIRECT3DSURFACE8 psurfSrc = NULL;
LPDIRECT3DSURFACE8 psurfDest = NULL;
hr = m_ptexCur->GetSurfaceLevel(0, &psurfDest);
if (bIsVolumeMap)
{
LPDIRECT3DVOLUME8 pvolSrc;
hr = ((LPDIRECT3DVOLUMETEXTURE8)ptex)->GetVolumeLevel(m_lwMipCur, &pvolSrc);
hr = LoadSurfaceFromVolumeSlice(pvolSrc, m_lwSliceCur, psurfDest);
ReleasePpo(&pvolSrc);
}
else if (!bIsCubeMap)
{
hr = ((LPDIRECT3DTEXTURE8)ptex)->GetSurfaceLevel(m_lwMipCur, &psurfSrc);
hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL,
D3DX_FILTER_TRIANGLE, 0);
}
else
{
hr = ((LPDIRECT3DCUBETEXTURE8)ptex)->GetCubeMapSurface(FaceType, m_lwMipCur, &psurfSrc);
hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL,
D3DX_FILTER_TRIANGLE, 0);
}
if (bViewAlpha)
{
// Move alpha channels into RGB (and set alpha to 0xff)
D3DLOCKED_RECT lr;
hr = psurfDest->LockRect(&lr, NULL, 0);
DWORD xp;
DWORD yp;
DWORD* pdwRow = (DWORD*)lr.pBits;
DWORD* pdw;
DWORD dwAlpha;
LONG dataBytesPerRow = 4 * sd.Width;
for (yp = 0; yp < sd.Height; yp++)
{
pdw = pdwRow;
for (xp = 0; xp < sd.Width; xp++)
{
dwAlpha = *pdw >> 24;
*pdw = 0xff000000 | (dwAlpha << 16) | (dwAlpha << 8) | (dwAlpha);
pdw++;
}
pdwRow += lr.Pitch / 4;
}
psurfDest->UnlockRect();
}
ReleasePpo(&psurfSrc);
ReleasePpo(&psurfDest);
return S_OK;
}
HRESULT CDxtexView::LoadSurfaceFromVolumeSlice(LPDIRECT3DVOLUME8 pVolume, UINT iSlice, LPDIRECT3DSURFACE8 psurf)
{
HRESULT hr;
D3DVOLUME_DESC vd;
D3DLOCKED_BOX lb;
D3DBOX box;
RECT rc;
pVolume->GetDesc(&vd);
box.Left = 0;
box.Right = vd.Width;
box.Top = 0;
box.Bottom = vd.Height;
box.Front = iSlice;
box.Back = iSlice + 1;
rc.left = 0;
rc.right = vd.Width;
rc.top = 0;
rc.bottom = vd.Height;
hr = pVolume->LockBox(&lb, &box, 0);
if (FAILED(hr))
return hr;
hr = D3DXLoadSurfaceFromMemory(psurf, NULL, NULL, lb.pBits, vd.Format, lb.RowPitch,
NULL, &rc, D3DX_FILTER_TRIANGLE, 0);
pVolume->UnlockBox();
return hr;
}
void CDxtexView::OnViewNegX()
{
BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_NEGATIVE_X, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
m_bTitleModsChanged = TRUE; // force title bar update
RenderScene();
Invalidate(); // force redraw of this view
}
void CDxtexView::OnUpdateViewNegX(CCmdUI* pCmdUI)
{
BOOL bEnable = GetDocument()->IsCubeMap();
pCmdUI->Enable(bEnable);
pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_NEGATIVE_X);
}
void CDxtexView::OnViewPosX()
{
BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_POSITIVE_X, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
m_bTitleModsChanged = TRUE; // force title bar update
RenderScene();
Invalidate(); // force redraw of this view
}
void CDxtexView::OnUpdateViewPosX(CCmdUI* pCmdUI)
{
BOOL bEnable = GetDocument()->IsCubeMap();
pCmdUI->Enable(bEnable);
pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_POSITIVE_X);
}
void CDxtexView::OnViewNegY()
{
BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_NEGATIVE_Y, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
m_bTitleModsChanged = TRUE; // force title bar update
RenderScene();
Invalidate(); // force redraw of this view
}
void CDxtexView::OnUpdateViewNegY(CCmdUI* pCmdUI)
{
BOOL bEnable = GetDocument()->IsCubeMap();
pCmdUI->Enable(bEnable);
pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_NEGATIVE_Y);
}
void CDxtexView::OnViewPosY()
{
BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_POSITIVE_Y, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
m_bTitleModsChanged = TRUE; // force title bar update
RenderScene();
Invalidate(); // force redraw of this view
}
void CDxtexView::OnUpdateViewPosY(CCmdUI* pCmdUI)
{
BOOL bEnable = GetDocument()->IsCubeMap();
pCmdUI->Enable(bEnable);
pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_POSITIVE_Y);
}
void CDxtexView::OnViewNegZ()
{
BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_NEGATIVE_Z, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
m_bTitleModsChanged = TRUE; // force title bar update
RenderScene();
Invalidate(); // force redraw of this view
}
void CDxtexView::OnUpdateViewNegZ(CCmdUI* pCmdUI)
{
BOOL bEnable = GetDocument()->IsCubeMap();
pCmdUI->Enable(bEnable);
pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_NEGATIVE_Z);
}
void CDxtexView::OnViewPosZ()
{
BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_POSITIVE_Z, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
m_bTitleModsChanged = TRUE; // force title bar update
RenderScene();
Invalidate(); // force redraw of this view
}
void CDxtexView::OnUpdateViewPosZ(CCmdUI* pCmdUI)
{
BOOL bEnable = GetDocument()->IsCubeMap();
pCmdUI->Enable(bEnable);
pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_POSITIVE_Z);
}
void CDxtexView::OnFileOpenFace()
{
GetDocument()->OpenCubeFace(m_CubeFaceCur);
}
void CDxtexView::OnUpdateFileOpenFace(CCmdUI* pCmdUI)
{
BOOL bEnable = (m_CubeFaceCur != D3DCUBEMAP_FACE_FORCE_DWORD);
pCmdUI->Enable(bEnable);
}
void CDxtexView::OnFileOpenAlphaFace()
{
GetDocument()->OpenAlphaCubeFace(m_CubeFaceCur);
}
void CDxtexView::OnUpdateFileOpenAlphaFace(CCmdUI* pCmdUI)
{
BOOL bEnable = (m_CubeFaceCur != D3DCUBEMAP_FACE_FORCE_DWORD);
pCmdUI->Enable(bEnable);
}
void CDxtexView::OnViewHigherVolumeSlice()
{
m_lwSliceCur++;
BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
UpdateDevice();
RenderScene();
m_bTitleModsChanged = TRUE; // force title bar update
Invalidate(); // force redraw of this view
}
void CDxtexView::OnUpdateViewHigherVolumeSlice(CCmdUI* pCmdUI)
{
pCmdUI->Enable(GetDocument()->IsVolumeMap() && m_lwSliceCur < (LONG)GetDocument()->DwDepthAt(m_lwMipCur) - 1);
}
void CDxtexView::OnViewLowerVolumeSlice()
{
m_lwSliceCur--;
BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
UpdateDevice();
RenderScene();
m_bTitleModsChanged = TRUE; // force title bar update
Invalidate(); // force redraw of this view
}
void CDxtexView::OnUpdateViewLowerVolumeSlice(CCmdUI* pCmdUI)
{
pCmdUI->Enable(GetDocument()->IsVolumeMap() && m_lwSliceCur > 0);
}